<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 Object是其他类的父类</title>
  <!-- 
  在 JavaScript ES5 中， `Object`  是所有对象的基类，几乎所有的对象都可以追溯到  `Object` 。这使得  `Object`  成为其他类或构造函数的父类。
  1. Object 的基本概念
  -  `Object`  是 JavaScript 中的一个内置构造函数，用于创建对象。
  - 所有 JavaScript 对象都继承自  `Object.prototype` ，这使得它们可以访问  `Object`  提供的方法。

  2. 作为父类的特性
  当一个类（构造函数）以  `Object`  为父类时，它可以继承  `Object`  的属性和方法。这包括：

  - 基本方法：如  `toString()` ,  `hasOwnProperty()` ,  `isPrototypeOf()` , 等等。
  - 属性访问：所有对象都可以访问  `Object.prototype`  上定义的属性和方法。

  3. 创建以 Object 为父类的类
  可以通过构造函数和原型链的方式创建以  `Object`  为父类的类。以下是一个示例：
  // 定义一个构造函数
  function Person(name, age) {
      this.name = name;
      this.age = age;
  }

  // 继承 Object 的方法
  Person.prototype = Object.create(Object.prototype);
  Person.prototype.constructor = Person;

  // 添加方法
  Person.prototype.sayHello = function() {
      console.log("Hello, my name is " + this.name);
  };

  // 创建实例
  var alice = new Person("Alice", 30);
  alice.sayHello(); // 输出: Hello, my name is Alice

  // 使用 Object 的方法
  console.log(alice.hasOwnProperty("name")); // 输出: true
  console.log(alice.toString()); // 输出: [object Object]
  4. 注意事项
  - 方法共享：通过原型继承的方法是共享的，这意味着所有实例都会共享这些方法，节省内存。
  - 实例属性：每个实例都有自己的属性，这些属性不会被共享。
  - 原型链：可以通过  `Object.getPrototypeOf(obj)`  或  `obj.__proto__`  访问对象的原型。

  5. 总结
  在 JavaScript ES5 中， `Object`  是所有对象的基类，几乎所有的对象都可以追溯到  `Object` 。通过将构造函数的原型设置为  `Object.prototype` ，可以实现以  `Object`  为父类的类。这使得类能够继承  `Object`  提供的属性和方法，从而实现代码的复用和共享。理解  `Object`  作为父类的特性对于掌握 JavaScript 的面向对象编程非常重要。
  -->
</head>
<body>

  <script>
    // 创建对象过程
    function createObject(o) {
      function F() {}
      F.prototype = o;
      return new F();
    }

    // 将Subtype和Supertype联系在一起
    // 寄生式函数
    function inheritPrototype(Subtype, Supertype) {
      // Subtype.prototype.__proto__ = Supertype.prototype
      // Object.setPrototypeOf(Subtype.prototype, Subtype.prototype)
      Subtype.prototype = createObject(Supertype.prototype);
      Object.defineProperty(Subtype.prototype, 'constructor', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: Subtype
      })
      Object.setPrototypeOf(Subtype, Supertype);
      // Subtype.__proto__ = Supertype
    }
  </script>

  <script>
    function Person() {}
    function Student() {}
    function Teacher() {}

    inheritPrototype(Student, Person);
    console.log(Student.prototype.__proto__ === Object.prototype); // false
    console.log(Person.prototype.__proto__ === Object.prototype); // true

    // 在Object的原型上添加方法和属性
    Object.prototype.sayHi = function () {
      console.log('hi');
    }
    Object.prototype.age = 18;
    console.log(Object.prototype.__proto__ === null, Object.age); // true undefined 18
    Object.sayHi() // hi

    const stu = new Student();
    stu.sayHi(); // hi
    console.log(stu.age); // 18

    // Object原型上本来就已经存放一些方法
    console.log(Object.prototype)
    console.log(stu.toString())

    // 函数对象也是最终继承自Object
    function foo() {}
    console.log(foo.age) // 18
  
  </script>
  
</body>
</html>